/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


/*************************************************************************
 * File: linkedlist.h
 *************************************************************************
 *\author: starlove
 *************************************************************************/

#ifndef __MLSE_LIBRARY_LINKEDLIST_H__
#define __MLSE_LIBRARY_LINKEDLIST_H__

template<typename T>
struct _LINKEDNODE
{
    _LINKEDNODE *next;
    T			val;
};

typedef void (LPREMOVELINKEDNODEFUNC)(void *p);

template<typename T>
class CSinglyLinkedList
{
public:
    typedef _LINKEDNODE<T> LINKEDNODE;
    typedef LINKEDNODE *LPLINKEDNODE;

    typedef struct _Iterator
    {
public:
        T val;
        const _Iterator& operator ++( int iv )
        {
            if(data)
            {
                data = data->next;
                if(data)
                    val = data->val;
            }
            else
            {
                data = NULL;
                val = NULL;
            }
            return *this;
        };

        bool operator ==( _Iterator& v )
        {
            return data == v.data;
        };

        bool operator !=( _Iterator& v )
        {
            return !(*this == v);
        };

        void operator =( LPLINKEDNODE v )
        {
            data = v;
            if(data)
                val = data->val;
        };
private:
        LPLINKEDNODE data;
    } Iterator,*LPIterator;

    CSinglyLinkedList():
        m_first(NULL)
        ,m_last(NULL)
        ,m_size(0)
    {};

    void push( T val )
    {
        LPLINKEDNODE pNode = m_nodeallocator.allocate();
        if (!pNode) return;
        pNode->next = NULL;
        pNode->val = val;

        if (!m_first||!m_last)
        {
            m_first = m_last = pNode;
        }
        else
        {
            m_last->next = pNode;
            m_last = pNode;
        }
    };

    void pop()
    {
        if(!m_first) return;
        LPLINKEDNODE pNode = m_first;
        m_first = m_first->next;
        pNode->next = NULL;
        m_nodeallocator.free(pNode);
        pNode = NULL;
        if (!m_first)
            m_last = NULL;
    };

    Iterator& begin()
    {
        m_it = m_first;
        return m_it;
    };

    Iterator& end()
    {
        m_it = NULL;
        return m_it;
    };

    T first()
    {
        return m_first ? m_first->val : NULL;
    };

    T last()
    {
        return m_last ? m_last->val : NULL;
    };

    void clear( LPREMOVELINKEDNODEFUNC pRemoveFunc = NULL )
    {
        if(!m_first) return;
        while (m_first)
        {
            if(pRemoveFunc)
                pRemoveFunc(&m_first->val);
            pop();
        }
        m_first = m_last = NULL;
    };

    size_t size()
    {
        return 0;
    };

private:
    volatile long	m_size;
    LINKEDNODE	*	m_first;
    LINKEDNODE	*	m_last;
    Iterator		m_it;
    CFixedAllocator<LINKEDNODE> m_nodeallocator;
};

#endif
